{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CVjHcUsRyM7I"
   },
   "source": [
    "# Retrieval-Augmented Generation(RAG) from Scratch with FTS, Vector Search and Hybrid Search"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WjJnK8VHx4r1"
   },
   "source": [
    "In this notebook, we will build a Retrieval-Augmented Generation(RAG) pipeline from scratch without using any popular libraries such as Langchain or Llamaindex.\n",
    "\n",
    "RAG is a technique that retrieves related documents to the user's question, combines them with LLM-base prompt, and sends them to LLMs like GPT to produce more factually accurate generation."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pvGgyVYb7JNs"
   },
   "source": [
    "Lets Split RAG Pipeline into 5 parts:\n",
    "\n",
    "1. Data loading\n",
    "2. Chunking and Embedding\n",
    "3. Ingest data in Vector Store\n",
    "4. FTS, Vector Search and Hybrid search Retrieval & Prompt preparation\n",
    "5. Answer Generation using results of FTS, Vector Search and Hybrid search all of them"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "DTE0cKVh7oES"
   },
   "source": [
    "Here is an image illustrating the RAG process\n",
    "\n",
    "![flow]()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rmiiI22M4aPK"
   },
   "source": [
    "## Install Dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "aGP9H97ghb9-",
    "outputId": "0c04ae1a-63b6-43ee-eb92-a32d2c00162e"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m37.3/37.3 MB\u001b[0m \u001b[31m23.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25h"
     ]
    }
   ],
   "source": [
    "# Install\n",
    "!pip install transformers scikit-learn docx2txt datasets nltk lancedb openai==0.28 tantivy pylance -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ygbayCQH6tlr"
   },
   "source": [
    "### Set OPENAI API KEY as env variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "id": "hOP0kua_q2lp"
   },
   "outputs": [],
   "source": [
    "# Set OPENAI_API_KEY\n",
    "\n",
    "import os\n",
    "import openai\n",
    "\n",
    "openai.api_key = \"sk-proj-...\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BcX8B04yCp7x"
   },
   "source": [
    "## Data Loading"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "GNdKH6GuOuo3",
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "outputId": "e439cca4-e5e8-4c30-ddaa-b20a040dfe77"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "--2025-04-18 09:46:48--  https://raw.githubusercontent.com/lancedb/vectordb-recipes/main/tutorials/RAG-from-Scratch/lease.txt\n",
      "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
      "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n",
      "HTTP request sent, awaiting response... 200 OK\n",
      "Length: 5248 (5.1K) [text/plain]\n",
      "Saving to: ‘lease.txt’\n",
      "\n",
      "lease.txt           100%[===================>]   5.12K  --.-KB/s    in 0s      \n",
      "\n",
      "2025-04-18 09:46:48 (50.6 MB/s) - ‘lease.txt’ saved [5248/5248]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Load text\n",
    "!wget https://raw.githubusercontent.com/lancedb/vectordb-recipes/main/tutorials/RAG-from-Scratch/lease.txt\n",
    "\n",
    "# !wget link\n",
    "with open(\"lease.txt\", \"r\") as file:\n",
    "    text_data = file.read()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "J9ZADS66CuK9"
   },
   "source": [
    "## Data Chunking and Embedding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "n_O8DxuqGPKx",
    "outputId": "9a28525c-63a7-45ba-f5e2-20c2b506d19d"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stderr",
     "text": [
      "[nltk_data] Downloading package punkt to /root/nltk_data...\n",
      "[nltk_data]   Unzipping tokenizers/punkt.zip.\n"
     ]
    }
   ],
   "source": [
    "# Recursive Text Splitter\n",
    "\n",
    "import nltk\n",
    "\n",
    "nltk.download(\"punkt\")\n",
    "from nltk.tokenize import sent_tokenize\n",
    "import re\n",
    "\n",
    "\n",
    "def recursive_text_splitter(text, max_chunk_length=1000, overlap=100):\n",
    "    \"\"\"\n",
    "    Helper function for chunking text recursively\n",
    "    \"\"\"\n",
    "    # Initialize result\n",
    "    result = []\n",
    "\n",
    "    current_chunk_count = 0\n",
    "    separator = [\"\\n\", \" \"]\n",
    "    _splits = re.split(f\"({separator})\", text)\n",
    "    splits = [_splits[i] + _splits[i + 1] for i in range(1, len(_splits), 2)]\n",
    "\n",
    "    for i in range(len(splits)):\n",
    "        if current_chunk_count != 0:\n",
    "            chunk = \"\".join(\n",
    "                splits[\n",
    "                    current_chunk_count\n",
    "                    - overlap : current_chunk_count\n",
    "                    + max_chunk_length\n",
    "                ]\n",
    "            )\n",
    "        else:\n",
    "            chunk = \"\".join(splits[0:max_chunk_length])\n",
    "\n",
    "        if len(chunk) > 0:\n",
    "            result.append(\"\".join(chunk))\n",
    "        current_chunk_count += max_chunk_length\n",
    "\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "kQ9MggTd1nQU",
    "outputId": "9b4d52c8-a3e3-44ef-9de3-596a7f37d6ea"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Number of Chunks:  11\n"
     ]
    }
   ],
   "source": [
    "# Split the text using the recursive character text splitter\n",
    "chunks = recursive_text_splitter(text_data, max_chunk_length=100, overlap=10)\n",
    "print(\"Number of Chunks: \", len(chunks))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "frV9INBTDAsf"
   },
   "source": [
    "## Vector Store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "id": "c1IqsxywNt3t"
   },
   "outputs": [],
   "source": [
    "# Insert text chunks with their embeddings\n",
    "\n",
    "import lancedb\n",
    "from lancedb.embeddings import get_registry\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "\n",
    "\n",
    "embeddings = (\n",
    "    get_registry().get(\"sentence-transformers\").create(name=\"BAAI/bge-small-en-v1.5\")\n",
    ")\n",
    "\n",
    "\n",
    "class Documents(LanceModel):\n",
    "    vector: Vector(embeddings.ndims()) = embeddings.VectorField()\n",
    "    text: str = embeddings.SourceField()\n",
    "\n",
    "\n",
    "def prepare_data(chunks, embeddings):\n",
    "    \"\"\"\n",
    "    Helper function to prepare data to insert in LanceDB\n",
    "    \"\"\"\n",
    "    data = []\n",
    "    for chunk, embed in zip(chunks, embeddings):\n",
    "        temp = {}\n",
    "        temp[\"text\"] = chunk\n",
    "        temp[\"vector\"] = embed\n",
    "        data.append(temp)\n",
    "    return data\n",
    "\n",
    "\n",
    "def lanceDBConnection(chunks):\n",
    "    \"\"\"\n",
    "    LanceDB insertion\n",
    "    \"\"\"\n",
    "\n",
    "    db = lancedb.connect(\"/tmp/lancedb\")\n",
    "    # data = prepare_data(chunks, embeddings)\n",
    "    table = db.create_table(\"documents\", schema=Documents, mode=\"overwrite\")\n",
    "\n",
    "    data = [{\"text\": s} for s in chunks]\n",
    "    # ingest data in table\n",
    "    table.add(data)\n",
    "    return table\n",
    "\n",
    "\n",
    "# create and add table in table\n",
    "table = lanceDBConnection(chunks)\n",
    "\n",
    "# Create a fts index before the hybrid search\n",
    "table.create_fts_index(\"text\", replace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7nzycQrJDEc4"
   },
   "source": [
    "## Retriever & Prompt preparation"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Query Type: FTS"
   ],
   "metadata": {
    "id": "mLB4MguQPJeA"
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "id": "uEUUo1Jko05R"
   },
   "outputs": [],
   "source": [
    "# Retriever\n",
    "question = \"What is issue date of lease?\"\n",
    "\n",
    "# FTS Search\n",
    "fts_result = table.search(question, query_type=\"fts\").limit(5).to_list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "LeOo_JkFwyqY",
    "outputId": "fcd648a1-93b2-4a81-ab50-2231c9767d20"
   },
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "[' as defined in Section 2 of this Article II, and shall terminate on May 31, 2020 (\"the Termination Date\"); provided, however, that at the option of Tenant, Tenant may renew this Lease for five additional successive one- year terms at a Monthly Rent of $100,000 per month, provided that notice of such renewal is given in writing no less than 120 days prior to the Termination Date or the expiration of any one-year renewal term. Tenant may at any time cancel this Lease and terminate all of its obligations hereunder by the payment of $300,000, plus all other amounts then due',\n",
       " ' 2 elmonteleaseforfiling.htm MATERIAL CONTRACT\\nCOMMERCIAL LEASE AGREEMENT\\n\\n\\n\\nTHIS LEASE AGREEMENT is made and entered into on December 1, 2013, by and between Temple CB, LLC, whose address is 4350 Temple City Boulevard, El Monte, California 91731 (hereinafter referred to as \"Landlord\"), and Okra Energy, Inc., whose address is 4350 Temple City Boulevard, El Monte, California 91731 (hereinafter referred to as \"Tenant\").\\n\\n\\n\\nARTICLE I - GRANT OF LEASE\\n\\n\\n\\nLandlord, in consideration of the rents to be paid and the covenants',\n",
       " ' consideration of the rents to be paid and the covenants and agreements to be performed and observed by the Tenant, does hereby lease to the Tenant and the Tenant does hereby lease and take from the Landlord the property described in Exhibit \"A\" attached hereto and by reference made a part hereof (the \"Leased Premises\"), together with, as part of the parcel, all improvements located thereon.\\n\\n\\n\\nARTICLE II - LEASE TERM\\n\\n\\n\\nSection l.  Term of Lease.  The term of this Lease shall begin on the Commencement Date, as defined in Section 2 of this Article II,',\n",
       " ' of $300,000, plus all other amounts then due under this Lease.\\n\\n\\n\\nSection 2.  Commencement Date. The \"Commencement Date\" shall mean  December 1, 2013.\\n\\n\\n\\nARTICLE III - EXTENSIONS\\n\\n\\n\\nThe parties hereto may elect to extend this Agreement upon such terms and conditions as may be agreed upon in writing and signed by the parties at the time of any such extension.\\n\\n\\n\\nARTICLE IV - DETERMINATION OF RENT\\n\\n\\n\\nSection 1. Monthly Rent: The Tenant agrees to pay the Landlord and the Landlord agrees to accept, during the term hereof, at',\n",
       " ' released from all liability for the return of such security to the Tenant.\\n\\n\\n\\nARTICLE VI - TAXES\\n\\n\\n\\nSection l.  Personal Property Taxes.  The Tenant shall be liable for all taxes levied against any leasehold interest of the Tenant or personal property and trade fixtures owned or placed by the Tenant in the Leased Premises.\\n\\n\\n\\nSection 2.  Real Estate Taxes.  During the continuance of this lease Landlord shall deliver to Tenant a copy of any real estate taxes and assessments against the Leased Property. From and after the Commencement Date, the Tenant shall pay to Landlord not']"
      ]
     },
     "metadata": {},
     "execution_count": 23
    }
   ],
   "source": [
    "fts_context = [r[\"text\"] for r in fts_result]\n",
    "fts_context"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Query Type: Vector Search"
   ],
   "metadata": {
    "id": "SfOU-iGLQdUy"
   }
  },
  {
   "cell_type": "code",
   "source": [
    "# Retriever\n",
    "question = \"What is issue date of lease?\"\n",
    "\n",
    "# Vector Search\n",
    "vs_result = table.search(question, query_type=\"vector\").limit(10).to_list()"
   ],
   "metadata": {
    "id": "jLyEHSH4QkCF"
   },
   "execution_count": 49,
   "outputs": []
  },
  {
   "cell_type": "code",
   "source": [
    "vs_context = [r[\"text\"] for r in vs_result]\n",
    "vs_context"
   ],
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Aq7UT6dtQyvE",
    "outputId": "52141ea0-acd9-4ce9-dd55-01f712eb28ab"
   },
   "execution_count": 50,
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "[' as defined in Section 2 of this Article II, and shall terminate on May 31, 2020 (\"the Termination Date\"); provided, however, that at the option of Tenant, Tenant may renew this Lease for five additional successive one- year terms at a Monthly Rent of $100,000 per month, provided that notice of such renewal is given in writing no less than 120 days prior to the Termination Date or the expiration of any one-year renewal term. Tenant may at any time cancel this Lease and terminate all of its obligations hereunder by the payment of $300,000, plus all other amounts then due',\n",
       " ' of $300,000, plus all other amounts then due under this Lease.\\n\\n\\n\\nSection 2.  Commencement Date. The \"Commencement Date\" shall mean  December 1, 2013.\\n\\n\\n\\nARTICLE III - EXTENSIONS\\n\\n\\n\\nThe parties hereto may elect to extend this Agreement upon such terms and conditions as may be agreed upon in writing and signed by the parties at the time of any such extension.\\n\\n\\n\\nARTICLE IV - DETERMINATION OF RENT\\n\\n\\n\\nSection 1. Monthly Rent: The Tenant agrees to pay the Landlord and the Landlord agrees to accept, during the term hereof, at',\n",
       " ' consideration of the rents to be paid and the covenants and agreements to be performed and observed by the Tenant, does hereby lease to the Tenant and the Tenant does hereby lease and take from the Landlord the property described in Exhibit \"A\" attached hereto and by reference made a part hereof (the \"Leased Premises\"), together with, as part of the parcel, all improvements located thereon.\\n\\n\\n\\nARTICLE II - LEASE TERM\\n\\n\\n\\nSection l.  Term of Lease.  The term of this Lease shall begin on the Commencement Date, as defined in Section 2 of this Article II,',\n",
       " \" Commencement Date, the Tenant shall pay to Landlord not later than twenty-one (21) days after the day on which the same may become initially due, all real estate taxes and assessments applicable to the Leased Premises, together with any interest and penalties lawfully imposed thereon as a result of Tenant's late payment thereof, which shall be levied upon the Leased Premises during the term of this Lease.\\n\\n\\n\\nSection 3.  Contest of Taxes.  The Tenant, at its own cost and expense, may, if it shall in good faith so desire, contest by appropriate proceedings the amount of\",\n",
       " ' agrees to accept, during the term hereof, at such place as the Landlord shall from time to time direct by notice to the Tenant, monthly rent of $40,000.\\n\\n\\nSection 2.  Late Fee.  A late fee in the amount of 5% of the Monthly Rent shall be assessed if payment is not postmarked or received by Landlord on or before the tenth day of each month.\\n\\n\\n\\nARTICLE V - SECURITY DEPOSIT\\n\\n\\n\\nThe Tenant has deposited with the Landlord the sum of Twenty Thousand Dollars ($20,000.00) as security for the full and faithful performance by the Tenant',\n",
       " ' 2 elmonteleaseforfiling.htm MATERIAL CONTRACT\\nCOMMERCIAL LEASE AGREEMENT\\n\\n\\n\\nTHIS LEASE AGREEMENT is made and entered into on December 1, 2013, by and between Temple CB, LLC, whose address is 4350 Temple City Boulevard, El Monte, California 91731 (hereinafter referred to as \"Landlord\"), and Okra Energy, Inc., whose address is 4350 Temple City Boulevard, El Monte, California 91731 (hereinafter referred to as \"Tenant\").\\n\\n\\n\\nARTICLE I - GRANT OF LEASE\\n\\n\\n\\nLandlord, in consideration of the rents to be paid and the covenants',\n",
       " ' proceedings, the Tenant shall have the right to contest the amount of any such tax and the Tenant shall have the right to withhold payment of any such tax, if the statute under which the Tenant is contesting such tax so permits.\\n\\n\\n\\nSection 4.  Payment of Ordinary Assessments.  The Tenant shall pay all assessments, ordinary and extraordinary, attributable to or against the Leased Premises not later than twenty-one (21) days after the day on which the same became initially due. The Tenant may take the benefit of any law allowing assessments to be paid in installments and in such event the',\n",
       " ' released from all liability for the return of such security to the Tenant.\\n\\n\\n\\nARTICLE VI - TAXES\\n\\n\\n\\nSection l.  Personal Property Taxes.  The Tenant shall be liable for all taxes levied against any leasehold interest of the Tenant or personal property and trade fixtures owned or placed by the Tenant in the Leased Premises.\\n\\n\\n\\nSection 2.  Real Estate Taxes.  During the continuance of this lease Landlord shall deliver to Tenant a copy of any real estate taxes and assessments against the Leased Property. From and after the Commencement Date, the Tenant shall pay to Landlord not',\n",
       " \" so desire, contest by appropriate proceedings the amount of any personal or real property tax. The Tenant may, if it shall so desire, endeavor at any time or times, by appropriate proceedings, to obtain a reduction in the assessed valuation of the Leased Premises for tax purposes. In any such event, if the Landlord agrees, at the request of the Tenant, to join with the Tenant at Tenant's expense in said proceedings and the Landlord agrees to sign and deliver such papers and instruments as may be necessary to prosecute such proceedings, the Tenant shall have the right to contest\",\n",
       " ' security for the full and faithful performance by the Tenant of all the terms of this lease required to be performed by the Tenant. Such sum shall be returned to the Tenant after the expiration of this lease, provided the Tenant has fully and faithfully carried out all of its terms. In the event of a bona fide sale of the property of which the leased premises are a part, the Landlord shall have the right to transfer the security to the purchaser to be held under the terms of this lease, and the Landlord shall be released from all liability for the return of such security']"
      ]
     },
     "metadata": {},
     "execution_count": 50
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Perform inbuilt Hybrid Search\n",
    "They have some off the shelf functionalities and a way to implement the custom Re-Ranking and Filtering Function here [Implement Custom Rerankers](https://lancedb.github.io/lancedb/hybrid_search/#building-custom-rerankers)"
   ],
   "metadata": {
    "id": "b36H_kzIQ3ks"
   }
  },
  {
   "cell_type": "code",
   "source": [
    "from lancedb.rerankers import LinearCombinationReranker\n",
    "\n",
    "reranker = LinearCombinationReranker(\n",
    "    weight=0.7\n",
    ")  # Weight = 0 Means pure Text Search (BM-25) and 1 means pure Sementic (Vector) Search\n",
    "\n",
    "hs_result = (\n",
    "    table.search(\n",
    "        question,\n",
    "        query_type=\"hybrid\",\n",
    "    )\n",
    "    .rerank(reranker=reranker)\n",
    "    .limit(5)\n",
    "    .to_list()\n",
    ")\n",
    "\n",
    "hs_context = [r[\"text\"] for r in hs_result]\n",
    "hs_context"
   ],
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "mi4HUE18Q9fn",
    "outputId": "50f013ea-75f8-4082-dd44-96bb93b32761"
   },
   "execution_count": 26,
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "[' released from all liability for the return of such security to the Tenant.\\n\\n\\n\\nARTICLE VI - TAXES\\n\\n\\n\\nSection l.  Personal Property Taxes.  The Tenant shall be liable for all taxes levied against any leasehold interest of the Tenant or personal property and trade fixtures owned or placed by the Tenant in the Leased Premises.\\n\\n\\n\\nSection 2.  Real Estate Taxes.  During the continuance of this lease Landlord shall deliver to Tenant a copy of any real estate taxes and assessments against the Leased Property. From and after the Commencement Date, the Tenant shall pay to Landlord not',\n",
       " ' consideration of the rents to be paid and the covenants and agreements to be performed and observed by the Tenant, does hereby lease to the Tenant and the Tenant does hereby lease and take from the Landlord the property described in Exhibit \"A\" attached hereto and by reference made a part hereof (the \"Leased Premises\"), together with, as part of the parcel, all improvements located thereon.\\n\\n\\n\\nARTICLE II - LEASE TERM\\n\\n\\n\\nSection l.  Term of Lease.  The term of this Lease shall begin on the Commencement Date, as defined in Section 2 of this Article II,',\n",
       " ' 2 elmonteleaseforfiling.htm MATERIAL CONTRACT\\nCOMMERCIAL LEASE AGREEMENT\\n\\n\\n\\nTHIS LEASE AGREEMENT is made and entered into on December 1, 2013, by and between Temple CB, LLC, whose address is 4350 Temple City Boulevard, El Monte, California 91731 (hereinafter referred to as \"Landlord\"), and Okra Energy, Inc., whose address is 4350 Temple City Boulevard, El Monte, California 91731 (hereinafter referred to as \"Tenant\").\\n\\n\\n\\nARTICLE I - GRANT OF LEASE\\n\\n\\n\\nLandlord, in consideration of the rents to be paid and the covenants',\n",
       " ' agrees to accept, during the term hereof, at such place as the Landlord shall from time to time direct by notice to the Tenant, monthly rent of $40,000.\\n\\n\\nSection 2.  Late Fee.  A late fee in the amount of 5% of the Monthly Rent shall be assessed if payment is not postmarked or received by Landlord on or before the tenth day of each month.\\n\\n\\n\\nARTICLE V - SECURITY DEPOSIT\\n\\n\\n\\nThe Tenant has deposited with the Landlord the sum of Twenty Thousand Dollars ($20,000.00) as security for the full and faithful performance by the Tenant',\n",
       " \" Commencement Date, the Tenant shall pay to Landlord not later than twenty-one (21) days after the day on which the same may become initially due, all real estate taxes and assessments applicable to the Leased Premises, together with any interest and penalties lawfully imposed thereon as a result of Tenant's late payment thereof, which shall be levied upon the Leased Premises during the term of this Lease.\\n\\n\\n\\nSection 3.  Contest of Taxes.  The Tenant, at its own cost and expense, may, if it shall in good faith so desire, contest by appropriate proceedings the amount of\"]"
      ]
     },
     "metadata": {},
     "execution_count": 26
    }
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "id": "3AoAKFBdFrCt"
   },
   "outputs": [],
   "source": [
    "# Context Prompt\n",
    "\n",
    "base_prompt = \"\"\"You are an AI assistant. Your task is to understand the user question, and provide an answer using the provided contexts. Every answer you generate should have citations in this pattern  \"Answer [position].\", for example: \"Earth is round [1][2].,\" if it's relevant.\n",
    "\n",
    "Your answers are correct, high-quality, and written by an domain expert. If the provided context does not contain the answer, simply state, \"The provided context does not have the answer.\"\n",
    "\n",
    "User question: {}\n",
    "\n",
    "Contexts:\n",
    "{}\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "txqygIfrDSQD"
   },
   "source": [
    "## Answer Generation"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Using FTS result"
   ],
   "metadata": {
    "id": "f9MS5tUFRsMY"
   }
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "4hhdqV9PqbA0",
    "outputId": "8021ee84-b9aa-452b-c4c5-aa7c3fed127b"
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "The issue date of the lease is December 1, 2013 [2].\n"
     ]
    }
   ],
   "source": [
    "import openai\n",
    "\n",
    "# Your prompt\n",
    "prompt = f\"{base_prompt.format(question, fts_context)}\"\n",
    "\n",
    "response = openai.ChatCompletion.create(\n",
    "    model=\"gpt-4o\",\n",
    "    temperature=0,\n",
    "    messages=[\n",
    "        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
    "        {\"role\": \"user\", \"content\": prompt},\n",
    "    ],\n",
    ")\n",
    "\n",
    "print(response.choices[0].message[\"content\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Using Vector Search result"
   ],
   "metadata": {
    "id": "PNNwcx_oR7sW"
   }
  },
  {
   "cell_type": "code",
   "source": [
    "# Your prompt\n",
    "prompt = f\"{base_prompt.format(question, vs_context)}\"\n",
    "\n",
    "response = openai.ChatCompletion.create(\n",
    "    model=\"gpt-4o\",\n",
    "    temperature=0,\n",
    "    messages=[\n",
    "        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
    "        {\"role\": \"user\", \"content\": prompt},\n",
    "    ],\n",
    ")\n",
    "\n",
    "print(response.choices[0].message[\"content\"])"
   ],
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "8DMsp4hoRrhT",
    "outputId": "9e3c954b-53b0-4d32-8ea4-16d7c7d896de"
   },
   "execution_count": 51,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "The issue date of the lease is December 1, 2013 [6].\n"
     ]
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Using Hybrid Search result"
   ],
   "metadata": {
    "id": "sMGBRBBcR94k"
   }
  },
  {
   "cell_type": "code",
   "source": [
    "# Your prompt\n",
    "prompt = f\"{base_prompt.format(question, hs_context)}\"\n",
    "\n",
    "response = openai.ChatCompletion.create(\n",
    "    model=\"gpt-4o\",\n",
    "    temperature=0,\n",
    "    messages=[\n",
    "        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
    "        {\"role\": \"user\", \"content\": prompt},\n",
    "    ],\n",
    ")\n",
    "\n",
    "print(response.choices[0].message[\"content\"])"
   ],
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "jCq0Pdv6RrHx",
    "outputId": "a9cdd5db-57cf-4cac-cdf7-c86502d6e896"
   },
   "execution_count": 48,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "The issue date of the lease is December 1, 2013 [3].\n"
     ]
    }
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}